<template>
    <div
      ref="containerRef"
      class="map-container"
      style="width: 100%; height: calc(100% - 67px)"
    >
      <!-- Three.js 场景会在这个容器中渲染 -->
      <div class="tooltip" ref="tooltipRef"></div>
    </div>
  </template>
    
  <script setup>
  import { ref, onMounted, onBeforeUnmount } from "vue";
  import * as THREE from "three";
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
  import { geoMercator } from "d3-geo";
  import LightSweepMaterial from "../../utils/lightSweepMaterial.js";
  import { RGBELoader } from "three-stdlib";
  import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";
  import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js";
  import {
    CSS2DObject,
    CSS2DRenderer,
  } from "three/examples/jsm/renderers/CSS2DRenderer.js";
  import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
  
  // 全局变量
  let jsondata = null;
  let camera = null;
  let scene = null;
  let renderer = null;
  let controls = null;
  let map = null;
  let midMap = null;
  let baseMap = null;
  let raycaster = new THREE.Raycaster();
  let mouse = new THREE.Vector2();
  let lastPick = null;
  let lightMesh = null;
  let lightMaterial = null;
  let gridHelper = null;
  let labelRenderer = new CSS2DRenderer();
  const ringWidth = 0.1;
  const T = Math.PI / 2;
  const projectionFn = geoMercator()
    .center([104.0, 37.5])
    .scale(80)
    .translate([0, 0]);
  
  // setup function variables
  const containerRef = ref(null);
  const tooltipRef = ref(null);
  const mapInitPosition = { x: 0, y: 6, z: 0 };
  const mapDepth = 6;
  const isAnimating = ref(true);
  
  const initializeThree = () => {
    const width = containerRef.value.clientWidth;
    const height = 1071;
  
    // 创建场景
    scene = new THREE.Scene();
    scene.background = new THREE.Color("#ffffff");
  
    // 创建相机
    camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
    camera.position.set(0, -20, 80);
  
    // 创建渲染器
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(width, height);
  
    // 将渲染器的DOM元素（canvas）添加到容器中
    containerRef.value.appendChild(renderer.domElement);
  
    // 添加控制器
    controls = new OrbitControls(camera, renderer.domElement);
  
    // 使用 RGBELoader 加载 HDR 环境贴图
    const loader = new RGBELoader();
    loader.load("http://47.105.210.118:10005/json/umhlanga_sunrise_1k.hdr", function (texture) {
      texture.mapping = THREE.EquirectangularReflectionMapping;
      scene.environment = texture;
    });
  
    // 添加扩散圈
    const geometry = new THREE.PlaneGeometry(290, 290);
    lightMaterial = new LightSweepMaterial();
    lightMesh = new THREE.Mesh(geometry, lightMaterial);
    scene.add(lightMesh);
  
    // 添加网格
    gridHelper = new THREE.GridHelper(2000, 100, "#bbb", "#bbb");
    gridHelper.rotation.x = -Math.PI / 2;
    gridHelper.position.set(0, -0.01, 0);
    scene.add(gridHelper);
  
    // 加载地图数据
    loadMapData();
  
    // 初始化 labelRenderer
    initLabelRenderer();
  
    // 开始渲染循环
    animate();
  };
  
  // 初始化 labelRenderer
  const initLabelRenderer = () => {
    const width = containerRef.value.clientWidth;
    const height = 1071;
    labelRenderer.domElement.style.position = "absolute";
    labelRenderer.domElement.style.top = "0px";
    labelRenderer.domElement.style.pointerEvents = "none";
    labelRenderer.setSize(width, height);
    containerRef.value.appendChild(labelRenderer.domElement);
  };
  // 加载地图数据的逻辑
  const loadMapData = () => {
    const loader = new THREE.FileLoader();
    loader.load("http://47.105.210.118:10005/json/ChinaMap.json", (data) => {
      jsondata = JSON.parse(data);
      createMap(jsondata);
      createMidMap(jsondata);
      createBaseMap(jsondata);
    });
  };
  
  // 创建地图
  const createMap = (data) => {
    map = new THREE.Object3D();
    const projection = getProjection();
    // 计算 data.features 中的最大 value 值
    var arr = data.features.map((elem) => elem.properties.subFeatureIndex);
    let filteredNumbers = arr.filter(
      (value) => typeof value === "number" && !isNaN(value)
    );
    const maxFeatureValue = Math.max(...filteredNumbers);
    // 地图数据处理
    const fontLoader = new FontLoader();
    fontLoader.load("/MFTianLiNoncommercial_Regular.json", (font) => {
      data.features.forEach((elem) => {
        // Map rendering logic
        const province = new THREE.Object3D();
        const { coordinates } = elem.geometry;
        coordinates.forEach((multiPolygon) => {
          multiPolygon.forEach((polygon) => {
            const shape = new THREE.Shape();
            const lineGeometry = new THREE.BufferGeometry();
            const pointsArray = [];
            for (let i = 0; i < polygon.length; i++) {
              const [x, y] = projection(polygon[i]);
              if (i === 0) {
                shape.moveTo(x, -y);
              } else {
                shape.lineTo(x, -y);
              }
              pointsArray.push(new THREE.Vector3(x, -y, mapDepth / 24));
            }
            lineGeometry.setFromPoints(pointsArray);
  
            const extrudeSettings = {
              depth: mapDepth / 24,
              bevelEnabled: false,
            };
            const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  
            // 动态计算 transmission 和 roughness 值
            const transmissionValue = Math.sqrt(
              elem.properties.subFeatureIndex / maxFeatureValue
            );
            const roughnessValue = Math.sqrt(
              elem.properties.subFeatureIndex / maxFeatureValue
            );
            // 配置 MeshPhysicalMaterial 参数
            const config = {
              color: "#9cb8e4",
              clearcoat: 0.5,
              reflectivity: 0.35,
              ior: 1.3,
              transmission: transmissionValue, // 计算后的透明度
              roughness: roughnessValue, // 计算后的粗糙度
              thickness: 0.1, // 固定厚度
            };
  
            // 使用 MeshPhysicalMaterial 创建材质
            const material = new THREE.MeshPhysicalMaterial(config);
  
            const mesh = new THREE.Mesh(geometry, material);
            const lineMaterial = new THREE.LineBasicMaterial({
              color: "white",
            });
            const line = new THREE.Line(lineGeometry, lineMaterial);
            province.properties = elem.properties;
            province.add(mesh);
            province.add(line);
          });
        });
        map.add(province);
  
        // **城市名称**
        // 获取城市名称的位置（使用质心作为位置）
        const cityName = elem.properties.name;
        const centroid = elem.properties.centroid ||
          elem.properties.center || [0, 0];
        if (centroid) {
          let label = createLabel(cityName, centroid, 0.01);
          map.add(label);
          const textGeometry = new TextGeometry(cityName, {
            font: font,
            size: 0.5, // 文本大小
            height: 0.02, // 文本厚度
            curveSegments: 32,
            bevelEnabled: true,
            bevelSize: 0,
            bevelThickness: 0,
          });
  
          // 创建材质
          const textMaterial = new THREE.MeshBasicMaterial({
            color: "#000000",
          });
  
          // 创建文字 Mesh
          const textMesh = new THREE.Mesh(textGeometry, textMaterial);
          // 设置文字位置
          const [x, y] = projectionFn(centroid);
          textMesh.position.set(x, -y, 0.26);
          textMesh.rotation.x = Math.PI; // 调整旋转
          textMesh.rotation.y = Math.PI;
          textMesh.rotation.z = Math.PI;
  
          // 添加城市名称到省份对象
          // province.add(textMesh);
        }
      });
  
      map.position.set(
        mapInitPosition.x,
        mapInitPosition.y,
        mapInitPosition.z + 7.5
      );
      scene.add(map);
    });
  };
  
  const createMidMap = (data) => {
    // 创建中间地图
    const midMap = new THREE.Object3D();
    const projection = getProjection();
    data.features.forEach((elem) => {
      const province = new THREE.Object3D();
      const { coordinates } = elem.geometry;
      coordinates.forEach((multiPolygon) => {
        multiPolygon.forEach((polygon) => {
          const shape = new THREE.Shape();
          const pointsArray = [];
          for (let i = 0; i < polygon.length; i++) {
            const [x, y] = projection(polygon[i]);
            if (i === 0) {
              shape.moveTo(x, -y);
            } else {
              shape.lineTo(x, -y);
            }
            pointsArray.push(new THREE.Vector3(x, -y, mapDepth));
          }
          // lineGeometry.setFromPoints(pointsArray);
  
          const extrudeSettings = {
            depth: mapDepth,
            bevelEnabled: false,
          };
          const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  
          // 配置 MeshPhysicalMaterial 参数
          const config = {
            color: "#d2ebff",
            transmission: 1, // 模拟玻璃效果
            thickness: 0.3, // 调整厚度
            roughness: 0.6, // 控制表面粗糙度
            ior: 1, // 设置折射率
            clearcoat: 0.5, // 添加清漆效果
            clearcoatRoughness: 0.1, // 清漆粗糙度
            reflectivity: 0.35, // 反射率
          };
  
          // 使用 MeshPhysicalMaterial 创建材质
          const material = new THREE.MeshPhysicalMaterial(config);
          const mesh = new THREE.Mesh(geometry, material);
          province.properties = elem.properties;
          province.add(mesh);
        });
      });
      midMap.add(province);
    });
    midMap.position.set(
      mapInitPosition.x,
      mapInitPosition.y,
      mapInitPosition.z + 1.5
    );
    scene.add(midMap); // 将地图添加到场景
  };
  
  const createBaseMap = (data) => {
    baseMap = new THREE.Object3D(); // 创建地图对象
    const projection = getProjection();
    const geometries = []; // 用于存储每个省份的几何体
  
    data.features.forEach((elem) => {
      const { coordinates } = elem.geometry;
      coordinates.forEach((multiPolygon) => {
        multiPolygon.forEach((polygon) => {
          const shape = new THREE.Shape();
          for (let i = 0; i < polygon.length; i++) {
            const [x, y] = projection(polygon[i]);
            if (i === 0) {
              shape.moveTo(x, -y); // 移动到轮廓的起点
            } else {
              shape.lineTo(x, -y); // 画轮廓线
            }
          }
          const extrudeSettings = {
            depth: mapDepth / 4,
            bevelEnabled: false,
          };
  
          // 使用当前省份的轮廓生成 ExtrudeGeometry
          const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
          geometry.translate(0, 0, 0); // 确保几何体位置正确
  
          geometries.push(geometry); // 将每个省份的几何体加入数组
        });
      });
    });
  
    // 使用 BufferGeometryUtils 合并几何体
    const mergedGeometry = mergeGeometries(geometries);
  
    // 创建材质
    const textureLoader = new THREE.TextureLoader();
    const matcap = textureLoader.load("http://47.105.210.118:10005/json/C7C7D7_4C4E5A_818393_6C6C74-512px.png");
    const material = new THREE.MeshMatcapMaterial({ matcap });
  
    // 将合并后的几何体创建为一个 Mesh
    const mergedMesh = new THREE.Mesh(mergedGeometry, material);
    console.log(mergedMesh);
  
    baseMap.add(mergedMesh); // 将合并后的 Mesh 添加到 baseMap
    baseMap.position.set(mapInitPosition.x, mapInitPosition.y, mapInitPosition.z);
    scene.add(baseMap); // 将地图添加到场景
  };
  
  const createLabel = (name, point, depth) => {
    const div = document.createElement("div");
    div.style.color = "#000";
    div.style.fontSize = "12px";
    div.style.textShadow = "1px 1px 2px #047cd6";
    div.textContent = name;
    const label = new CSS2DObject(div);
    label.scale.set(1, 1, 1);
    const [x, y] = projectionFn(point);
    label.position.set(x, -y, depth);
    return label;
  };
  // 设置投影函数
  const getProjection = () => {
    return geoMercator().center([104.0, 37.5]).scale(80).translate([0, 0]);
  };
  
  // 动画循环
  const animate = () => {
    if (!isAnimating.value) return;
    requestAnimationFrame(animate);
    labelRenderer.render(scene, camera);
    const elapsedTime = performance.now() / 3000;
    const stage = (elapsedTime / T) % 2;
  
    if (stage < 1) {
      lightMaterial.uniforms.innerRadius.value =
        1.5 * Math.abs(Math.sin(elapsedTime));
    } else {
      lightMaterial.uniforms.innerRadius.value = 0;
    }
  
    lightMaterial.uniforms.ringWidth.value = ringWidth;
  
    controls.update();
    renderer.render(scene, camera);
  };
  
  // 窗口调整大小
  const onWindowResize = () => {
    const width = containerRef.value.clientWidth;
    const height = containerRef.value.clientHeight;
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
    renderer.setSize(width, height);
  };
  
  onMounted(() => {
    isAnimating.value = true;
    labelRenderer = new CSS2DRenderer();
    initializeThree();
    window.addEventListener("resize", onWindowResize);
  });
  
  onBeforeUnmount(() => {
    window.removeEventListener("resize", onWindowResize);
    isAnimating.value = false;
    if (renderer) renderer.dispose();
    if (controls) controls.dispose();
    if (labelRenderer?.domElement?.parentNode) {
      labelRenderer.domElement.parentNode.removeChild(labelRenderer.domElement);
    }
  });
  </script>
    
  <style scoped>
  .map-container {
    position: relative;
  }
  </style>
    